/**
 * BACON (sdd.bacon@gmail.com)
 *
 * MainFrame - This class displays the main window.
 *
 * Copyright (c) 2010
 * @author David Pizzuto, Seamus Reynolds, Matt Schoen, Michael Stark
 * All Rights Reserved
 *
 * @version 0.1, 04/02/10
 *
 * http://code.google.com/p/bacon/
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package bacon.gui;

import java.awt.event.KeyEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowAdapter;
import java.io.IOException;
import javax.swing.*;

import bacon.BaconSystem;
import bacon.BrowserLaunch;
import bacon.ComicDatabase;
import bacon.ComicSite;
import bacon.LocalPrefReader;
import bacon.SortMethod;
import bacon.SwingInput;

public class MainFrame extends javax.swing.JFrame {

    /** Creates new form MainFrame */
    public MainFrame(ComicDatabase db, LocalPrefReader lp) {
        initComponents();
        database = db;
        lpr = lp;
        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent evt) {
                lpr.savePreferences();
                database.saveDatabase();
            }
        });
        if(db != null) displayCurrentComic();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        comicMenu = new javax.swing.JPopupMenu();
        editComicMenuItem = new javax.swing.JMenuItem();
        removeComicMenuItem = new javax.swing.JMenuItem();
        launchSiteMenuItem = new javax.swing.JMenuItem();
        mainComicPanel = new javax.swing.JPanel();
        prevButton = new javax.swing.JButton();
        nextButton = new javax.swing.JButton();
        comicPane = new javax.swing.JScrollPane();
        comicLabel = new javax.swing.JLabel();
        addComicButton = new javax.swing.JButton();
        aboutButton = new javax.swing.JButton();
        menuBar = new javax.swing.JMenuBar();
        fileMenu = new javax.swing.JMenu();
        preferencesMenuItem = new javax.swing.JMenuItem();
        exitMenuItem = new javax.swing.JMenuItem();
        sortMenu = new javax.swing.JMenu();
        sortByAuthorMenuItem = new javax.swing.JMenuItem();
        sortByNameMenuItem = new javax.swing.JMenuItem();
        sortByUpdateMenuItem = new javax.swing.JMenuItem();

        editComicMenuItem.setText("Edit Comic");
        editComicMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                editComicMenuItemActionPerformed(evt);
            }
        });
        comicMenu.add(editComicMenuItem);

        removeComicMenuItem.setText("Remove Comic");
        removeComicMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                removeComicMenuItemActionPerformed(evt);
            }
        });
        comicMenu.add(removeComicMenuItem);

        launchSiteMenuItem.setText("Launch Comic Site");
        launchSiteMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                launchSiteMenuItemActionPerformed(evt);
            }
        });
        comicMenu.add(launchSiteMenuItem);

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("BACON");
        setLocationByPlatform(true);
        addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                formKeyPressed(evt);
            }
        });

        prevButton.setText("Previous");
        prevButton.setFocusable(false);
        prevButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                prevButtonActionPerformed(evt);
            }
        });

        nextButton.setText("Next");
        nextButton.setFocusable(false);
        nextButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                nextButtonActionPerformed(evt);
            }
        });

        comicLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        comicLabel.setVerticalAlignment(javax.swing.SwingConstants.TOP);
        comicLabel.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        comicLabel.setVerticalTextPosition(javax.swing.SwingConstants.TOP);
        comicLabel.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mousePressed(java.awt.event.MouseEvent evt) {
                comicLabelMousePressed(evt);
            }
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                comicLabelMouseReleased(evt);
            }
        });
        comicPane.setViewportView(comicLabel);

        addComicButton.setText("Add Comic");
        addComicButton.setFocusable(false);
        addComicButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addComicButtonActionPerformed(evt);
            }
        });

        aboutButton.setText("About");
        aboutButton.setFocusable(false);
        aboutButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                aboutButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout mainComicPanelLayout = new javax.swing.GroupLayout(mainComicPanel);
        mainComicPanel.setLayout(mainComicPanelLayout);
        mainComicPanelLayout.setHorizontalGroup(
            mainComicPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(mainComicPanelLayout.createSequentialGroup()
                .addComponent(prevButton)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(nextButton, javax.swing.GroupLayout.PREFERRED_SIZE, 70, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(addComicButton)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(aboutButton)
                .addContainerGap(309, Short.MAX_VALUE))
            .addComponent(comicPane, javax.swing.GroupLayout.DEFAULT_SIZE, 594, Short.MAX_VALUE)
        );
        mainComicPanelLayout.setVerticalGroup(
            mainComicPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, mainComicPanelLayout.createSequentialGroup()
                .addComponent(comicPane, javax.swing.GroupLayout.DEFAULT_SIZE, 430, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(mainComicPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(prevButton)
                    .addComponent(nextButton)
                    .addComponent(addComicButton)
                    .addComponent(aboutButton)))
        );

        fileMenu.setText("File");

        preferencesMenuItem.setText("Preferences");
        fileMenu.add(preferencesMenuItem);

        exitMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F4, java.awt.event.InputEvent.ALT_MASK));
        exitMenuItem.setText("Exit");
        exitMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                exitMenuItemActionPerformed(evt);
            }
        });
        fileMenu.add(exitMenuItem);

        menuBar.add(fileMenu);

        sortMenu.setText("Sort");

        sortByAuthorMenuItem.setText("Sort by Author");
        sortByAuthorMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                sortByAuthorMenuItemActionPerformed(evt);
            }
        });
        sortMenu.add(sortByAuthorMenuItem);

        sortByNameMenuItem.setText("Sort by Name");
        sortByNameMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                sortByNameMenuItemActionPerformed(evt);
            }
        });
        sortMenu.add(sortByNameMenuItem);

        sortByUpdateMenuItem.setText("Sort by Latest Update");
        sortByUpdateMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                sortByUpdateMenuItemActionPerformed(evt);
            }
        });
        sortMenu.add(sortByUpdateMenuItem);

        menuBar.add(sortMenu);

        setJMenuBar(menuBar);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(mainComicPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(mainComicPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void exitMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exitMenuItemActionPerformed
        database.saveDatabase();
        lpr.savePreferences();
        System.exit(0);
    }//GEN-LAST:event_exitMenuItemActionPerformed

    private void sortByNameMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sortByNameMenuItemActionPerformed
        ComicSite.sortMethod = SortMethod.SORT_BY_ALPHABETICAL;
        database.sortComicList();
        lpr.setPreference("SortStyle", "A_TO_Z_ALPHABETICAL");
    }//GEN-LAST:event_sortByNameMenuItemActionPerformed

    private void sortByUpdateMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sortByUpdateMenuItemActionPerformed
        ComicSite.sortMethod = SortMethod.SORT_BY_DATE;
        database.sortComicList();
        lpr.setPreference("SortStyle", "DATE_LAST_UPDATED");
    }//GEN-LAST:event_sortByUpdateMenuItemActionPerformed

    private void editComicMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editComicMenuItemActionPerformed
        ComicSite cs = ComicDialog.show(this, database.getCurrentComic());
        if(cs == null) {
            //Dialog cancelled, do nothing
            //SwingInput.displayErrorMessage("Comic not edited.");
            return;
        }
        database.removeComic();
        database.addComic(cs);
        displayCurrentComic();
    }//GEN-LAST:event_editComicMenuItemActionPerformed

    private void removeComicMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeComicMenuItemActionPerformed
        ComicSite cs = database.getCurrentComic();
        if(cs != null && confirm("Remove " + cs.getTitle() + " from the comic database?",
                "Remove Comic")) {
            database.removeComic();
            displayCurrentComic();
        }
    }//GEN-LAST:event_removeComicMenuItemActionPerformed

    private void nextButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nextButtonActionPerformed
        displayNextComic(true);
    }//GEN-LAST:event_nextButtonActionPerformed

    private void prevButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_prevButtonActionPerformed
        displayNextComic(false);
    }//GEN-LAST:event_prevButtonActionPerformed

    private void formKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_formKeyPressed
        //System.out.format("KEY PRESSED: %d\n", evt.getKeyCode());
        switch(evt.getKeyCode()) {
            case KeyEvent.VK_LEFT:
                displayNextComic(false);
                break;
            case KeyEvent.VK_RIGHT:
                displayNextComic(true);
                break;
        }
    }//GEN-LAST:event_formKeyPressed

    private void comicLabelMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_comicLabelMousePressed
        if(database.hasComics() && evt.isPopupTrigger()) {
            comicMenu.show(evt.getComponent(), evt.getX(), evt.getY());
        }
    }//GEN-LAST:event_comicLabelMousePressed

    private void comicLabelMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_comicLabelMouseReleased
        if(database.hasComics() && evt.isPopupTrigger()) {
            comicMenu.show(evt.getComponent(), evt.getX(), evt.getY());
        }
    }//GEN-LAST:event_comicLabelMouseReleased

    private void launchSiteMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_launchSiteMenuItemActionPerformed
        ComicSite cs = database.getCurrentComic();
        if(cs != null) {
            try {
                BrowserLaunch.openUrl(cs.getUrl());
            } catch (IOException e) {
                SwingInput.displayErrorMessage("Could not load website: " + e.getMessage());
            }
        }
    }//GEN-LAST:event_launchSiteMenuItemActionPerformed

    private void addComicButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addComicButtonActionPerformed
        ComicSite cs = ComicDialog.show(this, null);
        if(cs == null) {
            //Dialog cancelled, do nothing
            //SwingInput.displayErrorMessage("Comic not created/added.");
            return;
        }
        database.addComic(cs);
        displayCurrentComic();
    }//GEN-LAST:event_addComicButtonActionPerformed

    private void aboutButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_aboutButtonActionPerformed
        // Displays a window with the license text and a link to the Google code site.
        JOptionPane.showMessageDialog(this, BaconSystem.ABOUT_TEXT, "About",
            JOptionPane.PLAIN_MESSAGE);
    }//GEN-LAST:event_aboutButtonActionPerformed

    private void sortByAuthorMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sortByAuthorMenuItemActionPerformed
        ComicSite.sortMethod = SortMethod.SORT_BY_AUTHOR;
        database.sortComicList();
        lpr.setPreference("SortStyle", "AUTHOR_NAME_A_TO_Z");
    }//GEN-LAST:event_sortByAuthorMenuItemActionPerformed

    /**
     * Displays a Yes/No confirmation dialog to the user and returns true if they hit Yes.
     *
     * @param msg   the Object to display
     * @param title the title string for the dialog
     * @return      true if the user hits Yes
     */
    public boolean confirm(Object msg, String title) {
        return JOptionPane.showConfirmDialog(this, msg, title, JOptionPane.YES_NO_OPTION,
            JOptionPane.PLAIN_MESSAGE) == JOptionPane.YES_OPTION;
    }

    /**
     * Displays the image and text from the corresponding ComicSite.
     *
     * @param site The ComicSite to display, or null to display nothing
     */
    public void displayComic(ComicSite site) {
        //for (ComicSite cs : database.getAllComics())
        //    System.out.println(cs.getTitle() + ":\t" + cs.getStrip().getFilePath());
        if (site != null) {
            site.getStrip().loadImage();
            setTitle(site.getTitle() + " - BACON");
            comicLabel.setText(site.getInfoString());
            Icon img = site.getStrip().getComicStripImage();
            comicLabel.setIcon(img);
        } else {
            setTitle("BACON");
            comicLabel.setText("");
            comicLabel.setIcon(null);
        }
    }

    /**
     * Displays the current comic in the database.
     */
    public void displayCurrentComic() {
        displayComic(database.getCurrentComic());
    }

    /**
     * Displays the next or previous comic from the database.
     *
     * @param next If true, the next image is displayed. If false, the previous is.
     */
    public void displayNextComic(boolean next) {
        if (next) displayComic(database.getNextComic());
        else displayComic(database.getPreviousComic());
    }

    /**
     * Displays an error message dialog to the user with the given message and title.
     *
     * @param msg   the Object to display
     * @param title the title string for the dialog
     */
    private void showError(Object msg, String title) {
        JOptionPane.showMessageDialog(this, msg, title, JOptionPane.ERROR_MESSAGE);
    }

    /**
     * Displays a message dialog to the user with the given message and title.
     *
     * @param msg   the Object to display
     * @param title the title string for the dialog
     */
    private void showMessage(Object msg, String title) {
        JOptionPane.showMessageDialog(this, msg, title, JOptionPane.PLAIN_MESSAGE);
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton aboutButton;
    private javax.swing.JButton addComicButton;
    private javax.swing.JLabel comicLabel;
    private javax.swing.JPopupMenu comicMenu;
    private javax.swing.JScrollPane comicPane;
    private javax.swing.JMenuItem editComicMenuItem;
    private javax.swing.JMenuItem exitMenuItem;
    private javax.swing.JMenu fileMenu;
    private javax.swing.JMenuItem launchSiteMenuItem;
    private javax.swing.JPanel mainComicPanel;
    private javax.swing.JMenuBar menuBar;
    private javax.swing.JButton nextButton;
    private javax.swing.JMenuItem preferencesMenuItem;
    private javax.swing.JButton prevButton;
    private javax.swing.JMenuItem removeComicMenuItem;
    private javax.swing.JMenuItem sortByAuthorMenuItem;
    private javax.swing.JMenuItem sortByNameMenuItem;
    private javax.swing.JMenuItem sortByUpdateMenuItem;
    private javax.swing.JMenu sortMenu;
    // End of variables declaration//GEN-END:variables
    private ComicDatabase database;
    private LocalPrefReader lpr;

}
